using DBLibrary.HLBJMemoryTool;
using DevExpress.Xpo;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Server.Services;
using System.ComponentModel.DataAnnotations;

namespace Server.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class FileController : ControllerBase
    {
        private readonly HLBJMemoryToolUnitOfWork _unitOfWork;
        private readonly IFtpService _ftpService;

        public FileController(HLBJMemoryToolUnitOfWork unitOfWork, IFtpService ftpService)
        {
            _unitOfWork = unitOfWork;
            _ftpService = ftpService;
        }

        // 获取所有文件类型
        [HttpGet("types")]
        public ActionResult<IEnumerable<FileTypeDto>> GetFileTypes()
        {
            try
            {
                var fileTypes = _unitOfWork.Query<FileType>().ToList();
                var result = fileTypes.Select(type => new FileTypeDto
                {
                    Id = type.Id,
                    TypeName = type.TypeName,
                    MemoryStrength = type.MemoryStrength
                }).ToList();
                return Ok(result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "获取文件类型失败", Error = ex.Message });
            }
        }

        // 根据用户名获取文件类型
        [HttpGet("types/user/{username}")]
        public ActionResult<IEnumerable<FileTypeDto>> GetFileTypesByUser(string username)
        {
            try
            {
                if (string.IsNullOrEmpty(username))
                {
                    return BadRequest(new { Message = "用户名不能为空" });
                }

                // 获取指定用户的文件类型，包括用户自己创建的和公共的(UserId为null的)
                var fileTypes = _unitOfWork.Query<FileType>()
                    .Where(t => t.UserId == null || (t.UserId != null && t.UserId.UserName == username))
                    .ToList();

                var result = fileTypes.Select(type => new FileTypeDto
                {
                    Id = type.Id,
                    TypeName = type.TypeName,
                    MemoryStrength = type.MemoryStrength
                }).ToList();
                return Ok(result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "获取文件类型失败", Error = ex.Message });
            }
        }

        // 根据用户ID获取文件类型
        [HttpGet("types/user/id/{userId}")]
        public ActionResult<IEnumerable<FileTypeDto>> GetFileTypesByUserId(int userId)
        {
            try
            {
                if (userId < 0)
                {
                    return BadRequest(new { Message = "用户ID无效" });
                }

                // 获取指定用户ID的文件类型，包括用户自己创建的和公共的(UserId为null的)
                var fileTypes = _unitOfWork.Query<FileType>()
                    .Where(t => t.UserId == null || (t.UserId != null && t.UserId.Id == userId))
                    .ToList();

                var result = fileTypes.Select(type => new FileTypeDto
                {
                    Id = type.Id,
                    TypeName = type.TypeName,
                    MemoryStrength = type.MemoryStrength
                }).ToList();
                return Ok(result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "获取文件类型失败", Error = ex.Message });
            }
        }

        // 根据ID获取单个文件类型信息
        [HttpGet("types/{id}")]
        public ActionResult<FileTypeDto> GetFileTypeById(long id)
        {
            try
            {
                var fileType = _unitOfWork.Query<FileType>().FirstOrDefault(t => t.Id == id);
                if (fileType == null)
                {
                    return NotFound(new { Message = "未找到指定的文件类型" });
                }

                var result = new FileTypeDto
                {
                    Id = fileType.Id,
                    TypeName = fileType.TypeName,
                    MemoryStrength = fileType.MemoryStrength
                };

                return Ok(result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "获取文件类型信息失败", Error = ex.Message });
            }
        }

        // 添加新的文件类型
        [HttpPost("types")]
        public ActionResult<FileTypeDto> AddFileType([FromBody][Required] AddFileTypeRequest request)
        {
            try
            {
                // 检查是否已存在同名类型，处理UserId可能为空的情况
                var existingType = string.IsNullOrEmpty(request.UserId) 
                    ? _unitOfWork.Query<FileType>().FirstOrDefault(t => t.TypeName == request.TypeName && t.UserId == null)
                    : _unitOfWork.Query<FileType>().FirstOrDefault(t => t.TypeName == request.TypeName && t.UserId != null && t.UserId.UserName == request.UserId);
                
                if (existingType != null)
                {
                    return BadRequest(new { Message = $"类型 '{request.TypeName}' 已存在" });
                }

                // 获取或创建用户，处理UserId为空的情况
                UserInfo? user = null;
                if (!string.IsNullOrEmpty(request.UserId))
                {
                    user = _unitOfWork.Query<UserInfo>().FirstOrDefault(u => u.UserName == request.UserId);
                    if (user == null)
                    {
                        user = new UserInfo(_unitOfWork)
                        {
                            UserName = request.UserId,
                            PassWord = "",
                            Name = request.UserId
                        };
                        _unitOfWork.Save(user);
                    }
                }

                var newFileType = new FileType(_unitOfWork)
                {
                    TypeName = request.TypeName,
                    MemoryStrength = request.MemoryStrength,
                    UserId = user // 设置用户关联，如果user为null则表示无用户关联
                };

                _unitOfWork.Save(newFileType);
                _unitOfWork.CommitChanges();

                var result = new FileTypeDto
                {
                    Id = newFileType.Id,
                    TypeName = newFileType.TypeName,
                    MemoryStrength = newFileType.MemoryStrength
                };

                return CreatedAtAction(nameof(GetFileTypes), new { id = newFileType.Id }, result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "添加文件类型失败", Error = ex.Message });
            }
        }

        // 删除文件类型
        [HttpDelete("types/{id}")]
        public ActionResult DeleteFileType(long id)
        {
            try
            {
                var fileType = _unitOfWork.Query<FileType>().FirstOrDefault(t => t.Id == id);
                if (fileType == null)
                {
                    return BadRequest(new { Message = "无效的文件类型ID" });
                }

                // 检查是否有文件正在使用此类型
                var hasFiles = _unitOfWork.Query<DBLibrary.HLBJMemoryTool.FileInfo>().Any(f => f.FileType == fileType);
                if (hasFiles)
                {
                    return BadRequest(new { Message = "无法删除，有文件正在使用此类型" });
                }

                _unitOfWork.Delete(fileType);
                _unitOfWork.CommitChanges();

                return Ok(new { Message = "文件类型删除成功" });
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "删除文件类型失败", Error = ex.Message });
            }
        }

        // 更新文件类型
        [HttpPut("types/{id}")]
        public ActionResult<FileTypeDto> UpdateFileType(long id, [FromBody][Required] AddFileTypeRequest request)
        {
            try
            {
                var fileType = _unitOfWork.Query<FileType>().FirstOrDefault(t => t.Id == id);
                if (fileType == null)
                {
                    return BadRequest(new { Message = "无效的文件类型ID" });
                }

                // 检查是否存在同名的其他类型
                var existingType = _unitOfWork.Query<FileType>().FirstOrDefault(t => t.TypeName == request.TypeName && t.Id != id);
                if (existingType != null)
                {
                    return BadRequest(new { Message = $"类型 '{request.TypeName}' 已存在" });
                }

                // 更新文件类型属性
                fileType.TypeName = request.TypeName;
                fileType.MemoryStrength = request.MemoryStrength;

                _unitOfWork.Save(fileType);
                _unitOfWork.CommitChanges();

                var result = new FileTypeDto
                {
                    Id = fileType.Id,
                    TypeName = fileType.TypeName,
                    MemoryStrength = fileType.MemoryStrength
                };

                return Ok(result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "更新文件类型失败", Error = ex.Message });
            }
        }

        // 根据用户ID（字符串类型）获取文件信息
        [HttpGet("user/{userId}")]
        public ActionResult<IEnumerable<FileWithLastTimestampDto>> GetFilesByUserId(string userId)
        {
            try
            {
                if (string.IsNullOrEmpty(userId))
                {
                    return BadRequest(new { Message = "用户ID不能为空" });
                }

                // 尝试将字符串转换为整数ID
                    if (int.TryParse(userId, out int parsedId))
                    {
                        return GetFilesByIntUserId(parsedId);
                    }
                    else
                    {
                        // 如果转换失败，尝试通过用户名查找用户
                        var user = _unitOfWork.Query<UserInfo>().FirstOrDefault(u => u.UserName == userId);
                        if (user == null)
                        {
                            return NotFound(new { Message = "未找到指定用户" });
                        }
                        
                        // 使用用户的整数ID调用另一个方法
                        return GetFilesByIntUserId(user.Id);
                    }
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "获取用户文件列表失败", Error = ex.Message });
            }
        }

        // 获取所有文件及其最后时间戳
        [HttpGet]
        public ActionResult<IEnumerable<FileWithLastTimestampDto>> GetFiles()
        {
            try
            {
                var files = _unitOfWork.Query<DBLibrary.HLBJMemoryTool.FileInfo>().ToList();
                var result = new List<FileWithLastTimestampDto>();

                foreach (var file in files)
                {
                    var lastTimestamp = _unitOfWork.Query<TimeStamp>()
                        .Where(ts => ts.FileId == file)
                        .ToList()  // 先加载到内存
                        .OrderByDescending(ts => Convert.ToDateTime(ts.Time))  // 然后在内存中排序
                        .FirstOrDefault();

                    var fileDto = new FileWithLastTimestampDto
                    {
                        Id = file.Id,
                        FileName = file.FileName,
                        SavedPath = file.SavedPath,
                        FtpPath = file.FtpPath,
                        FileTypeId = file.FileType?.Id ?? 0,
                        FileTypeName = file.FileType?.TypeName ?? string.Empty,
                        LastTimestamp = lastTimestamp != null ? new TimestampDto
                        {
                            Id= lastTimestamp.Id,
                            Time = Convert.ToDateTime(lastTimestamp.Time),
                            OpenTime = Convert.ToDateTime(lastTimestamp.OpenTime)
                        } : null
                    };

                    result.Add(fileDto);
                }

                return Ok(result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "获取文件列表失败", Error = ex.Message });
            }
        }



        // 根据用户ID（整数类型）获取文件信息
        [HttpGet("user/id/{userId:int}")]
        public ActionResult<IEnumerable<FileWithLastTimestampDto>> GetFilesByIntUserId(int userId)
        {
            try
            {
                if (userId < 0)
                {
                    return BadRequest(new { Message = "用户ID无效" });
                }

                // 获取指定用户的文件
                var files = _unitOfWork.Query<DBLibrary.HLBJMemoryTool.FileInfo>()
                    .Where(f => f.UserId != null && f.UserId.Id == userId)
                    .ToList();
                
                var result = new List<FileWithLastTimestampDto>();

                foreach (var file in files)
                {
                    var lastTimestamp = _unitOfWork.Query<TimeStamp>()
                        .Where(ts => ts.FileId == file)
                        .ToList()  // 先加载到内存
                        .OrderByDescending(ts => Convert.ToDateTime(ts.Time))  // 然后在内存中排序
                        .FirstOrDefault();

                    var fileDto = new FileWithLastTimestampDto
                    {
                        Id = file.Id,
                        FileName = file.FileName,
                        SavedPath = file.SavedPath,
                        FtpPath = file.FtpPath,
                        FileTypeId = file.FileType?.Id ?? 0,
                        FileTypeName = file.FileType?.TypeName ?? string.Empty,
                        LastTimestamp = lastTimestamp != null ? new TimestampDto
                        {
                            Id= lastTimestamp.Id,
                            Time = Convert.ToDateTime(lastTimestamp.Time),
                            OpenTime = Convert.ToDateTime(lastTimestamp.OpenTime)
                        } : null
                    };

                    result.Add(fileDto);
                }

                return Ok(result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "获取用户文件列表失败", Error = ex.Message });
            }
        }

        // 获取单个文件信息
        [HttpGet("{id}")]
        public ActionResult<FileWithLastTimestampDto> GetFile(long id)
        {
            try
            {
                var file = _unitOfWork.Query<DBLibrary.HLBJMemoryTool.FileInfo>().FirstOrDefault(f => f.Id == id);
                if (file == null)
                {
                    return NotFound(new { Message = "未找到指定的文件" });
                }

                var lastTimestamp = _unitOfWork.Query<TimeStamp>()
                    .Where(ts => ts.FileId == file)
                    .ToList()  // 先加载到内存
                    .OrderByDescending(ts => Convert.ToDateTime(ts.Time))  // 然后在内存中排序
                    .FirstOrDefault();

                var fileDto = new FileWithLastTimestampDto
                {
                    Id = file.Id,
                    FileName = file.FileName,
                    SavedPath = file.SavedPath,
                    FtpPath = file.FtpPath,
                    FileTypeId = file.FileType?.Id ?? 0,
                    FileTypeName = file.FileType?.TypeName ?? string.Empty,
                    LastTimestamp = lastTimestamp != null ? new TimestampDto
                    {
                        Id= lastTimestamp.Id,
                        Time = Convert.ToDateTime(lastTimestamp.Time),
                        OpenTime = Convert.ToDateTime(lastTimestamp.OpenTime)
                    } : null
                };

                return Ok(fileDto);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "获取文件信息失败", Error = ex.Message });
            }
        }

        // 添加新文件 - 支持完整文件信息保存到fileinfo表
        [HttpPost]
        [HttpPost("add")]
        public ActionResult<FileWithLastTimestampDto> AddFile([FromBody][Required] AddFileRequest request)
        {
            try
            {
                var fileType = _unitOfWork.Query<FileType>().FirstOrDefault(t => t.Id == request.FileTypeId);
                if (fileType == null)
                {
                    return BadRequest(new { Message = "无效的文件类型ID" });
                }

                // 获取用户信息
                UserInfo userInfo = null;
                if (request.UserId.HasValue)
                {
                    userInfo = _unitOfWork.Query<UserInfo>().FirstOrDefault(u => u.Id == request.UserId.Value);
                    if (userInfo == null)
                    {
                        return BadRequest(new { Message = "无效的用户ID" });
                    }
                }

                var newFile = new DBLibrary.HLBJMemoryTool.FileInfo(_unitOfWork)
                {
                    FileName = request.FileName,
                    SavedPath = request.SavedPath,
                    FileType = fileType,
                    FtpPath = request.FtpPath
                };
                
                // 只有当userInfo不为null时才设置UserId属性
                if (userInfo != null)
                {
                    newFile.UserId = userInfo;
                }

                _unitOfWork.Save(newFile);

                // 确保Time和OpenTime不为空
                var timeValue = request.Time.ToString();
                var openTimeValue = request.OpenTime.ToString();
                
                var newTimestamp = new TimeStamp(_unitOfWork)
                {
                    FileId = newFile,
                    Time =  DateTime.Now.ToString(),
                    OpenTime = DateTime.Now.ToString()
                };

                _unitOfWork.Save(newTimestamp);
                _unitOfWork.CommitChanges();

                var result = new FileWithLastTimestampDto
                {
                    Id = newFile.Id,
                    FileName = newFile.FileName,
                    SavedPath = newFile.SavedPath,
                    FileTypeId = newFile.FileType.Id,
                    FileTypeName = newFile.FileType.TypeName,
                    LastTimestamp = new TimestampDto
                    {
                        Time = request.Time,
                        OpenTime = request.OpenTime
                    }
                };

                return CreatedAtAction(nameof(GetFiles), new { id = newFile.Id }, result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "添加文件失败", Error = ex.Message });
            }
        }

        // 添加新的时间戳（支持传统路径格式）
        [HttpPost("{fileId}/timestamps")]
        public ActionResult<TimestampDto> AddTimestamp(long fileId, [FromBody][Required] AddTimestampRequest request)
        {
            try
            {
                var file = _unitOfWork.Query<DBLibrary.HLBJMemoryTool.FileInfo>().FirstOrDefault(f => f.Id == fileId);
                if (file == null)
                {
                    return BadRequest(new { Message = "无效的文件ID" });
                }

                var newTimestamp = new TimeStamp(_unitOfWork)
                {
                    FileId = file,
                    Time = request.Time?.ToString() ?? DateTime.Now.ToString(),
                    OpenTime = request.OpenTime?.ToString() ?? DateTime.Now.ToString()
                };

                _unitOfWork.Save(newTimestamp);
                _unitOfWork.CommitChanges();

                var result = new TimestampDto
                {
                    Id = newTimestamp.Id,
                    Time = Convert.ToDateTime(newTimestamp.Time),
                    OpenTime = Convert.ToDateTime(newTimestamp.OpenTime)
                };

                return CreatedAtAction(nameof(GetFiles), new { id = fileId }, result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "添加时间戳失败", Error = ex.Message });
            }
        }

        // 添加新的时间戳（支持前端api/file/timestamp格式）
        [HttpPost("timestamp")]
        public ActionResult<TimestampDto> AddTimestampFromBody([FromBody] TimestampRequestBody request)
        {
            try
            {
                if (request == null || request.FileId <= 0)
                {
                    return BadRequest(new { Message = "文件ID不能为空" });
                }

                var file = _unitOfWork.Query<DBLibrary.HLBJMemoryTool.FileInfo>().FirstOrDefault(f => f.Id == request.FileId);
                if (file == null)
                {
                    return BadRequest(new { Message = "无效的文件ID" });
                }

                var newTimestamp = new TimeStamp(_unitOfWork)
                {
                    FileId = file,
                    Time = request.Time?.ToString() ?? DateTime.Now.ToString(),
                    OpenTime = request.OpenTime?.ToString() ?? DateTime.Now.ToString()
                };

                _unitOfWork.Save(newTimestamp);
                _unitOfWork.CommitChanges();

                var result = new TimestampDto
                {
                    Id = newTimestamp.Id,
                    Time = Convert.ToDateTime(newTimestamp.Time),
                    OpenTime = Convert.ToDateTime(newTimestamp.OpenTime)
                };

                return CreatedAtAction(nameof(GetFiles), new { id = request.FileId }, result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "添加时间戳失败", Error = ex.Message });
            }
        }

        // 删除文件 - 支持两种路径格式
        [HttpDelete("{id}")]
        [HttpDelete("delete/{id}")]
        public async Task<ActionResult> DeleteFile(long id)
        {
            try
            {
                var file = _unitOfWork.Query<DBLibrary.HLBJMemoryTool.FileInfo>().FirstOrDefault(f => f.Id == id);
                if (file == null)
                {
                    return BadRequest(new { Message = "无效的文件ID" });
                }

                // 如果有FTP路径，则删除FTP上的文件
                if (!string.IsNullOrEmpty(file.FtpPath))
                {
                    bool ftpDeleteResult = await _ftpService.DeleteFileFromFtpAsync(file.FtpPath);
                    if (!ftpDeleteResult)
                    {
                        // 记录警告但继续执行，确保数据库记录仍然被删除
                        return StatusCode(500, new { Message = "文件删除成功，但删除FTP文件时出错" });
                    }
                }

                // 先删除相关的时间戳记录（级联删除）
                var timestamps = _unitOfWork.Query<TimeStamp>().Where(ts => ts.FileId == file).ToList();
                foreach (var timestamp in timestamps)
                {
                    _unitOfWork.Delete(timestamp);
                }

                // 然后删除文件本身
                _unitOfWork.Delete(file);
                _unitOfWork.CommitChanges();

                return Ok(new { Message = "文件删除成功" });
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "删除文件失败", Error = ex.Message });
            }
        }

        // 获取文件复习时间信息（包含时间戳列表）
        [HttpGet("timestamps/{fileId}")]
        public ActionResult<object> GetFileTimestamps(long fileId)
        {
            try
            {
                var file = _unitOfWork.Query<DBLibrary.HLBJMemoryTool.FileInfo>().FirstOrDefault(f => f.Id == fileId);
                if (file == null)
                {
                    return BadRequest(new { Message = "无效的文件ID" });
                }

                var timestamps = _unitOfWork.Query<TimeStamp>()
                    .Where(ts => ts.FileId == file)
                    .ToList();

                var timestampsCount = timestamps.Count;
                var lastTimestamp = timestamps
                    .OrderByDescending(ts => Convert.ToDateTime(ts.Time))
                    .FirstOrDefault();

                var lastReviewTime = lastTimestamp != null ? Convert.ToDateTime(lastTimestamp.Time) : DateTime.Now;
               
                List<TimestampDto> timestampResponses = timestamps.Select(ts => new TimestampDto
                {
                    Id = ts.Id,
                    Time = Convert.ToDateTime(ts.Time),
                    OpenTime = Convert.ToDateTime(ts.OpenTime)
                }).ToList();
              

                // 返回匿名类型，包含客户端所需的所有字段
                var result = new 
                {
                    FileId = fileId,
                    FileName = file.FileName,
                    LastReviewTime = lastReviewTime,
                    ReviewCount = timestampsCount,
                   
                    Timestamps = timestampResponses
                };

                return Ok(result);
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { Message = "获取文件时间戳信息失败", Error = ex.Message });
            }
        }



       
    }

    // DTO 类定义
    public class FileTypeDto
    {
        public long Id { get; set; }
        public string TypeName { get; set; } = string.Empty;
        public double MemoryStrength { get; set; }
    }

    public class TimestampDto
    {
        public long Id { get; set; }
        public DateTime Time { get; set; }
        public DateTime OpenTime { get; set; }
    }

    public class FileWithLastTimestampDto
    {
        public long Id { get; set; }
        public string FileName { get; set; } = string.Empty;
        public string SavedPath { get; set; } = string.Empty;
        public string FtpPath { get; set; } = string.Empty;
        public long FileTypeId { get; set; }
        public string FileTypeName { get; set; } = string.Empty;
        public TimestampDto? LastTimestamp { get; set; }
    }

    public class AddFileRequest
    {
        [Required]
        public string FileName { get; set; } = string.Empty;

        [Required]
        public string SavedPath { get; set; } = string.Empty;

        [Required]
        public long FileTypeId { get; set; }

        public int? UserId { get; set; } // 修改为int?类型以匹配数据库的UserInfo.Id
        public string FtpPath { get; set; } = string.Empty;
        public DateTime Time { get; set; } = DateTime.Now;
        public DateTime OpenTime { get; set; } = DateTime.Now;
    }

    public class AddTimestampRequest
    {
        public DateTime? Time { get; set; }
        public DateTime? OpenTime { get; set; }
    }

    public class TimestampRequestBody
    {
        public long FileId { get; set; }
        public DateTime? Time { get; set; }
        public DateTime? OpenTime { get; set; }
    }

    public class AddFileTypeRequest
    {
        [Required]
        public string TypeName { get; set; } = string.Empty;
        
        [Required]
        [Range(0.1, double.MaxValue, ErrorMessage = "记忆强度必须大于0")]
        public double MemoryStrength { get; set; }
        
        public string UserId { get; set; } = string.Empty;
    }

    public class ReviewInfoDto
    {
        public long FileId { get; set; }
        public string FileName { get; set; } = string.Empty;
        public DateTime LastReviewTime { get; set; }
        public int ReviewCount { get; set; }
        public double MemoryStrength { get; set; }
        public DateTime NextReviewTime { get; set; }
        public bool IsDueForReview { get; set; }
    }
}